# -*- coding: utf-8 -*-
"""
Created on Wed Nov 15 10:22:02 2017

@author: za-xuzhaoye
"""
import pandas as pd
import numpy as np
import copy
import math

#strategy: if hstetf-1.0316hzetf>up, short hstetf, long hzetf
#if hstetf-1.0316hzetf<down, long hstetf, short hzetf

mktdata=pd.read_csv('D:\FOF_strategy\A&H_ETF_data\detail_price.csv')
pclose=mktdata['close'].values
popen=mktdata['open'].values
phigh = mktdata['high'].values
plow = mktdata['low'].values

mktdata1=pd.read_csv('D:\FOF_strategy\A&H_ETF_data\detail_price1.csv')
pclose1=mktdata1['close'].values
popen1=mktdata1['open'].values
phigh1 = mktdata1['high'].values
plow1 = mktdata1['low'].values

OrderedDict={'Profit':np.nan,'AnnualExpR':np.nan,'AnnualVOL':np.nan,
                     'Sharpe':np.nan,'DrawdownMax':np.nan,'Calmar':np.nan,
                     'TradeTimes':np.nan,'AvgHoldPeriod':np.nan}

def backtest(mktdata,pclose,popen,pclose1,popen1,mktdata1):    
    '''define signals'''
    diff=pclose1-1.0316*pclose
    mean=diff.mean()
    std=diff.std()
    up=mean+std
    down=mean-std
    
    diff_chart=pd.Series(diff,index=range(len(pclose)))
    down_line=pd.Series(down,index=range(len(pclose)))
    up_line=pd.Series(up,index=range(len(pclose)))
    mean_line=pd.Series(mean,index=range(len(pclose)))
    
    chart=pd.concat([diff_chart,up_line,down_line,mean_line],axis=1)
    chart.columns=['diff','up','down','mean']
    chart.plot(figsize=(15,7))
    
    tmp1=diff>up 
    tmp2=diff<down
    #if hstetf-1.0316hzetf>up, short hstetf, long hzetf
    #if hstetf-1.0316hzetf<down, long hstetf, short hzetf
    
    sgn_short1=np.where(tmp1==True,-1,0)
    sgn_long1=np.where(tmp2==True,1,0)
    sgn1=sgn_short1+sgn_long1
    
    sgn_short=np.where(tmp2==True,-1,0)
    sgn_long=np.where(tmp1==True,1,0)
    sgn=sgn_short+sgn_long
    
    #sgn_short_plot=pd.DataFrame(sgn_short)
    #pylab.plot(sgn_short_plot.index,sgn_short_plot.values, '^', color='lime', markersize=12,
    #                   label='sgn_short')

    sgn_hd1 = np.zeros(len(sgn1))
    index_long1=np.zeros(len(sgn))
    index_short1=np.zeros(len(sgn))
    
    popen1 = mktdata1['open'].values
    pclose1 = mktdata1['close'].values
#    phigh1 = mktdata1['high'].values
#    plow1 = mktdata1['low'].values
    
    sgn_hd = np.zeros(len(sgn))
    index_long=np.zeros(len(sgn))
    index_short=np.zeros(len(sgn))
    
    popen = mktdata['open'].values
    pclose = mktdata['close'].values
#    phigh = mktdata['high'].values
#    plow = mktdata['low'].values

    for i in np.arange(len(mktdata)):
        if i>0:
            if (sgn_long[i-1] == 1):
                sgn_hd[i] = sgn[i-1] 
                if(sgn_hd[i-1]<sgn_hd[i]):
                  index_long[i] = - np.sign(sgn_hd[i]) * popen[i] 
                else:
                 index_long[i]=0
                
            if  (sgn_short[i-1]==-1):
                sgn_hd[i] = sgn[i-1] 
                if(sgn_hd[i-1]>sgn_hd[i]):
                  index_short[i] = - np.sign(sgn_hd[i]) * popen[i] 
                else:
                 index_long[i]=0
    
            
            
    for j in np.arange(len(mktdata1)):
        if j>0:
            if (sgn_long1[j-1] == 1):
                sgn_hd1[j] = sgn1[j-1] 
                if(sgn_hd1[j-1]<sgn_hd1[j]):
                 index_long1[j] = - np.sign(sgn_hd1[j]) * popen1[j] 
                else:
                 index_long1[j]=0
                
            if  (sgn_short1[j-1]==-1):
                sgn_hd1[j] = sgn1[j-1] 
                if(sgn_hd1[j-1]>sgn_hd1[j]):
                 index_short1[j] = - np.sign(sgn_hd1[j]) * popen1[j] 
                else:
                 index_short1[j]=0
            
#    d = {'sgn_long':sgn_long, 'sgn_short': sgn_short, 'sgn_hd':sgn_hd,'index_long':index_long,'index_short':index_short,'pclose':pclose,
#         'sgn_long1':sgn_long1, 'sgn_short1': sgn_short1, 'sgn_hd1':sgn_hd1,'index_long1':index_long1,'index_short1':index_short1,'pclose1':pclose1,}
#    tdbook=pd.DataFrame(d, columns=['sgn_long','sgn_short','sgn_hd','index_long','index_short','pclose','sgn_long1','sgn_short1', 'sgn_hd1','index_long1','index_short1','pclose1'])
    d = {'index_long':index_long,'index_short':index_short,'pclose':pclose,
             'index_long1':index_long1,'index_short1':index_short1,'pclose1':pclose1,}
    tdbook=pd.DataFrame(d, columns=['index_long','index_short','pclose','index_long1','index_short1','pclose1'])
    tdbook.insert(0,column='datetime',value=mktdata['datetime'])
    
    return tdbook,index_long,index_short,pclose,index_long1,index_short1,pclose1
#    return tdbook
#%%
# calculate result

tdbook,index_long,index_short,pclose,index_long1,index_short1,pclose1= backtest(mktdata,pclose,popen,pclose1,popen1,mktdata1)
    
def CalculateResult(tdbook, index_long, index_short, index_long1, index_short1,TAU=365, rate=1.0007e-4, unit=100, Cap0=100000.0):
    
    if len(index_long) == 0:
            d = OrderedDict()
            d['AnnualExpR'] = np.nan
            d['AnnualVOL'] = np.nan
            d['Sharpe'] = np.nan
            d['DrawdownMax'] = np.nan
            d['Calmar'] = np.nan
            d['TradeTimes'] = np.nan
            d['WinningRatio'] = np.nan
            d['AvgWinning'] = np.nan
            d['AvgLosing'] = np.nan
            d['AvgHoldPeriod'] = np.nan
            CalResult = pd.DataFrame(d.items(), columns = ['Parameter', 'Value'])
            CalResult.index=CalResult['Parameter']
            del CalResult['Parameter']
            TradeRecord = pd.DataFrame()
    
    else:
            size = np.zeros(len(tdbook))  
            size1 = np.zeros(len(tdbook))          
            Cap = np.zeros(len(tdbook)) + Cap0                      
#            HoldPeriod = np.zeros(len(index_long))                      
#            HoldPeriod1 = np.zeros(len(index_long))

            Captmp = copy.copy(Cap0)
                        
            for ii in np.arange(len(index_long)):
               
                if index_long[ii]<0 and index_short1[ii]>0:
                    size1[ii] = 0
                    Captmp = Captmp+index_short1[ii]*size[ii-1]*unit
                    
                    size[ii] = np.floor(Captmp /abs(index_long[ii])/unit)
                    Captmp = Captmp+ index_long[ii]* size[ii] * unit
                        
                    if size[ii-1]>1 and size1[ii-1]==0:
                        size[ii]=size[ii-1]
                        size1[ii]=size1[ii-1] 
                            
                        
                elif index_short[ii]>0 and index_long1[ii]<0:
                    size[ii]=0
                    Captmp=Captmp+index_short[ii]*size[ii-1]*unit
                    
                    size1[ii] = np.floor(Captmp /abs(index_long1[ii])/unit)
                    Captmp = Captmp + index_long1[ii] * size1[ii] * unit
                    
                    if size[ii-1]==0 and size1[ii-1]>1:
                        size[ii]=size[ii-1]
                        size1[ii]=size1[ii-1] 
                    
                else:
                    size[ii]=size[ii-1]
                    size1[ii]=size1[ii-1]
#                    Captmp=size[ii]*pclose[ii]+size1[ii]*pclose1[ii]
                    
                if index_short[ii]+1 <= len(tdbook):
                    Cap[index_short[ii]+1:] = Captmp
#                    HoldPeriod[ii] = index_short[ii] - index_long[ii] + 1
#                    HoldPeriod1[ii] = index_short1[ii] - index_long1[ii] + 1
                        
#                    HoldPeriod=sgn_hd.count('1',start=0,end=len(sgn_hd))
            
            pnl = tdbook['index_long'] + tdbook['index_short'] + tdbook['index_long1'] + tdbook['index_short1'] #earning/loss                
            turnover = abs(tdbook['index_long']) + abs(tdbook['index_short'])+abs(tdbook['index_long1']) + abs(tdbook['index_short1'])    
            commission = turnover * rate                               
    #        slippage = slip * 2 * abs(tdbook['sgn_hd'])                  
    #        pnl_net = pnl - commission - slippage   
    #           
    #            tdbook['commission'] = commission
    #        tdbook['slippage'] = slippage
            tdbook['pnl'] = pnl
#            AvgHoldPeriod = HoldPeriod.mean()
#            AvgHoldPeriod1 = HoldPeriod1.mean()    # 平均持仓周期
            Capfloat = Cap + pnl * size * unit                      # 实时资金浮动
#            Return = np.log(Capfloat / Capfloat.shift(1))               # 收益率
            Return= Capfloat/Cap0-1
            
            tdbook['size'] = size
            tdbook['size1']=size1
            tdbook['Captmp']=Captmp
            tdbook['turnover'] = turnover
            tdbook['commission'] = commission * size * unit
            tdbook['Capital'] = Cap
            tdbook['CapitalFloat'] = Capfloat
            tdbook['Return'] = Return
            
            AnnualExpR = Return.mean() * TAU                            # 年化预期收益
            AnnualVOL = Return.std() * math.sqrt(TAU)                   # 年化波动率
            Sharpe = AnnualExpR/AnnualVOL                               # 夏普比率
            TradeTimes = len()                                    # 交易次数
            tmp = Capfloat / Cap - 1
            TradeResult = tmp[index_short].values                        #每笔交易盈亏比例
            WinningTimes = len(TradeResult[TradeResult>0])
            LosingTimes = len(TradeResult[TradeResult<0])
            WinningRatio = float(WinningTimes) / (float(WinningTimes) + float(LosingTimes))  # 胜率
            AvgWinning = TradeResult[TradeResult>0].mean()
            AvgLosing = TradeResult[TradeResult<0].mean()
            Drawdown = (Capfloat - Capfloat.cummax()) / Capfloat.cummax()   # 回撤
            DrawdownMax = - Drawdown.min()                                # 最大回撤
            Calmar = AnnualExpR / DrawdownMax                           # Calmar比率
            Profit = Capfloat.values[-1]/Cap0 - 1
            tdbook['Drawdown'] = Drawdown
        
            #        StartTime = tdbook['datetime'].iloc[0].strftime('%Y-%m-%d %H:%M:%S')
            #        EndTime = tdbook['datetime'].iloc[-1].strftime('%Y-%m-%d %H:%M:%S')
            StartTime = tdbook['datetime'].iloc[0]
            EndTime = tdbook['datetime'].iloc[-1]        
            d = OrderedDict()
            d['StartTime'] = StartTime
            d['EndTime'] = EndTime
            d['symbol'] = tdbook['symbol'].iloc[0]
            d['Profit'] = Profit
            d['AnnualExpR'] = AnnualExpR
            d['AnnualVOL'] = AnnualVOL
            d['Sharpe'] = Sharpe
            d['DrawdownMax'] = DrawdownMax
            d['Calmar'] = Calmar
            d['TradeTimes'] = TradeTimes
            d['WinningRatio'] = WinningRatio
            d['AvgWinning'] = AvgWinning
            d['AvgLosing'] = AvgLosing
#            d['AvgHoldPeriod'] = AvgHoldPeriod
            
            CalResult = pd.DataFrame(d.items(), columns = ['Parameter', 'Value'])
            CalResult.index=CalResult['Parameter']
            del CalResult['Parameter']
            
            TradeRecord=pd.DataFrame()
            TradeRecord['ReturnPerTrade'] = TradeResult
#            TradeRecord['HoldPerTrade'] = HoldPeriod
            tdbook.index=tdbook['datetime']
            #            tdbook=tdbook.drop('datetime',axis=1)
    return tdbook, CalResult, TradeRecord

        
            
